#pragma once

#include<iostream>
#include<string>
#include<vector>
#include<semaphore.h>

template<class T>
class RingQueue
{
    private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }

    public:
    RingQueue(int cap):_cap(cap),_ring_queue(_cap),_productor_step(0),_consumer_step(0);
    {
        sem_init(&_room_sem,0,_cap);
        sem_init(&_data_sem,0,0);
    }
    void Enqueue(const T& in)
    {
        P(_room_sem);
        _ring_queue[_productor_step++] = in;
        _productor_step %= _cap;
        V(_data_sem);
    }
     void Pop(T* out)
    {
        P(_data_sem);
        *out = _ring_queue[_consumer_step++];
        _consumer_step %= _cap;
        V(_room_sem);
    }

    private:
    std::vector<T> _ring_queue;
    int _cap;

    int _productor_step;
    int _consumer_step;

    sem_t _room_sem;
    sem_t _data_sem;
}